package com.think.common.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

public class JSonUtil {
	public static final Charset JSON_ENCODE_CHARSET = Charset.forName("UTF-8");

    private static final ObjectMapper jsonMapper = new ObjectMapper();

    private JSonUtil() {

    }

    public static JsonGenerator jsonGenerator(OutputStream output)
            throws IOException {
        JsonGenerator jGenerator = jsonMapper.getJsonFactory()
                .createJsonGenerator(output);
        return jGenerator;
    }

    public static JsonGenerator jonsGenerator(Writer writer) throws IOException {
        JsonGenerator jGenerator = jsonMapper.getJsonFactory()
                .createJsonGenerator(writer);
        return jGenerator;
    }

    public static <T> byte[] toJsonByteArray(T bean) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
        toJson(bean, baos);
        return baos.toByteArray();
    }

    public static <T> String toJson(T bean) {
        Writer writer = new StringWriter();
        toJson(bean, writer);
        return writer.toString();
    }

    public static <T> void toJson(T bean, OutputStream outputStream) {
        toJson(bean, new OutputStreamWriter(outputStream, JSON_ENCODE_CHARSET));
    }

    public static <T> void toJson(T bean, Writer writer) {
        try {
            JsonGenerator jsonGenerator = jsonMapper.getJsonFactory()
                    .createJsonGenerator(writer);
            jsonMapper.writeValue(jsonGenerator, bean);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T fromJson(String json, Class<T> valueType) {
        return fromJson(new StringReader(json), valueType);
    }

    public static <T> T fromJson(InputStream inputStream, Class<T> valueType) {
        return fromJson(new InputStreamReader(inputStream, JSON_ENCODE_CHARSET), valueType);
    }

    public static <T> T fromJson(byte[] bytes, Class<T> valueType) {
        return fromJson(new InputStreamReader(new ByteArrayInputStream(bytes), JSON_ENCODE_CHARSET), valueType);
    }

    public static <T> T fromJson(byte[] bytes, int offset, int length, Class<T> valueType) {
        return fromJson(new InputStreamReader(new ByteArrayInputStream(bytes, offset,length), JSON_ENCODE_CHARSET), valueType);
    }

    public static <T> T fromJson(Reader reader, Class<T> valueType) {
        try {
            return jsonMapper.readValue(reader, valueType);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T fromJson(InputStream inputStream,
                                 TypeReference<T> typeReference) {
        return fromJson(new InputStreamReader(inputStream, JSON_ENCODE_CHARSET), typeReference);
    }

    public static <T> T fromJson(String s, TypeReference<T> typeReference) {
        return fromJson(new StringReader(s), typeReference);
    }

    public static <T> T fromJson(byte[] bytes, TypeReference<T> typeReference) {
        return fromJson(new InputStreamReader(new ByteArrayInputStream(bytes), JSON_ENCODE_CHARSET), typeReference);
    }

    public static <T> T fromJson(byte[] bytes, int offset, int length, TypeReference<T> typeReference) {
        return fromJson(new InputStreamReader(new ByteArrayInputStream(bytes, offset, length), JSON_ENCODE_CHARSET), typeReference);
    }



    public static <T> T fromJson(Reader reader, TypeReference<T> typeReference) {
        try {
            return jsonMapper.readValue(reader, typeReference);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> getJsonObj(String json) {
        return (Map<String, Object>) fromJson(json, Map.class);
    }

    @SuppressWarnings("unchecked")
    public static List<Object> parseArray(String jsonString) {
        return fromJson(jsonString, new TypeReference<List<Object>>() {
        });
    }

    public static <T> List<T> parseArray(String jsonString, Class<?> clazz) {
        try {
            return jsonMapper.readValue(jsonString, jsonMapper.getTypeFactory().constructCollectionType(List.class, clazz));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> List<T> parseArray(byte[] bytes, int offset, int length, Class<?> clazz) {
        try {
            return jsonMapper.readValue(bytes,offset,length, jsonMapper.getTypeFactory().constructCollectionType(List.class, clazz));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
